﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO;

namespace Prism.Core.Storage
{
    /// <summary>
    /// 群组储存管理器，提供群组分散存储技术。
    /// </summary>
    public sealed class GroupStorageManager : StorageManager, IGroupDataSaver
    {
        public GroupStorageManager()
            : base()
        {
        }

        public GroupStorageManager(string profilePath)
            : base(profilePath)
        {
        }

        /// <summary>
        /// 指定配置文件名称以及目录位置初始化。
        /// </summary>
        /// <param name="profileName">配置文件名称。</param>
        /// <param name="rootDir">配置文件所在的目录位置。</param>
        public GroupStorageManager(string profileName, string rootDir)
            : base(profileName, rootDir)
        {
        }

        /// <summary>
        /// 验证该群组是否存在。
        /// </summary>
        /// <param name="_group">被验证的群组。</param>
        /// <returns>返回该群组是否存在的布尔值。</returns>
        public bool EnsureGroup(Group _group)
        {
            var q = from g in this.Profile.GroupList
                    where g.Name == _group.Name
                    select g;
            if (q.Count() == 1)
                return true;
            else return false;
        }

        /// <summary>
        /// 写入数据。
        /// </summary>
        /// <param name="accessName">访问名称。</param>
        /// <param name="stream">数据源的流。</param>
        /// <param name="group">所属群组。</param>
        public void AddData(string accessName, Stream stream, Group group)
        {
            this.AddData(accessName, stream, this.DataTable.LastedVersion, group);
        }

        /// <summary>
        /// 写入数据，并指定版本。
        /// </summary>
        /// <param name="accessName">访问名称。</param>
        /// <param name="stream">数据源的流。</param>
        /// <param name="version">指定的版本。</param>
        /// <param name="group">所属群组。</param>
        public void AddData(string accessName, Stream stream, Version version, Group group)
        {
            // 如果总表为空，则新建一个差分表送入总表，写入第一个文件，并计入长度。
            if (this.DataTable.IsEmpty)
            {
                var dataList = new DifferentialDataList();
                dataList.Version = new Version();
                this.DataTable.Add(dataList);
                dataList.Version.Value = version.Value;
                this.DataTable.LastedVersion.Value = version.Value;
                this.OnCheckGroup(group);
                dataList.AddData(accessName, group.Name, stream, this.DataTable);

            }
            // 如果总表不为空。
            else
            {
                var q = from i in this.DataTable
                        where i.Version == version
                        select i;
                var count = q.Count();
                // 如果找到了对应的版本，则送入数据。
                if (count == 1)
                {
                    var target = q.Single();
                    // 写入磁盘
                    this.OnCheckGroup(group);
                    target.AddData(accessName, group.Name, stream, this.DataTable);
                }
                // 如果找不到对应的版本，则新建一个差分数据表。
                else if (count == 0)
                {
                    var dataList = new DifferentialDataList();
                    dataList.Version = version;
                    this.DataTable.Add(dataList);
                    // 写入磁盘
                    this.OnCheckGroup(group);
                    dataList.AddData(accessName, group.Name, stream, this.DataTable);
                }
            }

            // 更新配置文件。
            this.UpdateProfileToDisk();
        }

        void OnCheckGroup(Group group)
        {
            if (!this.EnsureGroup(group))
            {
                this.Profile.GroupList.Add(group);
                this.Profile.DataTable.GroupDataLength.Add(group.Name, -1);
            }
        }
    }
}
